package com.huawei.springboot2023.core.config;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 模块名称：
 * 模块类型：
 * 编码人：周城阳
 * 编码时间：2023/3/29
 */
@Component
// webscoket服务上下文路径： 前端连接写法： ws://localhost:8090/websocket/wsdemo
@ServerEndpoint(value = "/websocket/wsdemo")
public class MyWebSocketConfig {



    static{
        System.out.println("----------------------------------");
        System.out.println("------   WebSocket服务启动   -------");
        System.out.println("---------                ----------");
        System.out.println("----------------------------------");
    }

    private Session session; // 当前客户端的会话对象
    private String sessionID;// 客户端id

    /**
     * CopyOnWriteArraySet ： 读写线程安全集合（可以去重）
     */
    private static CopyOnWriteArraySet<MyWebSocketConfig> copyOnWriteArraySet = new CopyOnWriteArraySet<MyWebSocketConfig>();

    /**
     * 开启一个WebSocket服务，将服务对象实例交由SpringBoot管理
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    /**
     * 当客户端连接到服务器时，该方法会触发调用
     * @param session  WebSocket客户端会话对象（客户端对象）
     */
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("------客户端连接服务器");

        // 1. 一旦有链接，就将当前连接添加到集合中
        copyOnWriteArraySet.add(this);
        System.out.println("-----现有连接【"+copyOnWriteArraySet.size()+"】个");
        this.session = session;
        // 2. 每一个客户端的session对象都有唯一的id标识
        this.sessionID = session.getId();
    }

    /**
     * 当客户端断开连接时触发的方法
     */
    @OnClose
    public void onClose() {
        System.out.println("------客户端断开连接");
    }

    /**
     * 当客户端发送消息时回调
     * @param message 客户端发送的消息
     */
    @OnMessage
    public void onMessage(String message) {
        System.out.println("----客户端发送消息："+message);
        // 马上群发给所有的客户端
        this.allSendMessage(message);
    }

    /**
     * 发送消息、创建连接出现异常回调
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("-----发生错误："+error.getMessage()+"客户端id："+session.getId());
    }

    /**
     * 广播方法： 发送消息给所有的客户端
     */
    public void allSendMessage(String msg){
        for(MyWebSocketConfig webSocketConfig:copyOnWriteArraySet){
            try {
                webSocketConfig.session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 点对点发送
     * @param saveSessionID 要发送的客户端id
     * @param msg 发送的信息
     */
    public void sendToSession(String saveSessionID,String msg){
        for(MyWebSocketConfig webSocketConfig:copyOnWriteArraySet){
            if(webSocketConfig.session.getId().equals(saveSessionID)){
                try {
                    webSocketConfig.session.getBasicRemote().sendText(msg);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

}

